package org.example.exampreparationtreasure.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.example.exampreparationtreasure.mapper.CategoryMapper;
import org.example.exampreparationtreasure.mapper.QuestionMapper;
import org.example.exampreparationtreasure.model.entity.Categories;
import org.example.exampreparationtreasure.model.entity.Question;
import org.example.exampreparationtreasure.model.vo.CategoryTreeNode;
import org.example.exampreparationtreasure.service.CategoryService;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 分类服务实现。
 * <p>
 * 功能：
 * <ul>
 *   <li>构建分类树（含递归 children）。</li>
 *   <li>按父 ID 查询直接子分类。</li>
 *   <li>按分类查询题目（不递归）。</li>
 *   <li>递归查询所有后代分类（扁平结果）。</li>
 *   <li>按父分类聚合所有后代分类中的题目。</li>
 * </ul>
 * </p>
 *
 * <p>
 * 设计约定：题目仅出现在叶子分类；父分类 ID 顶层可为 0 或 null。
 * </p>
 */
@Service
public class CategoryServiceImpl implements CategoryService {

    private final CategoryMapper categoryMapper;
    private final QuestionMapper questionMapper;

    public CategoryServiceImpl(CategoryMapper categoryMapper, QuestionMapper questionMapper) {
        this.categoryMapper = categoryMapper;
        this.questionMapper = questionMapper;
    }

    @Override
    /**
     * 构建完整分类树：
     * 1) 查询全量分类；2) 建立 id→节点 映射；3) 链接父子关系；4) 递归排序；5) 返回根节点集合。
     */
    public List<CategoryTreeNode> getCategoryTree() {
        List<Categories> all = categoryMapper.selectList(null);
        Map<Long, CategoryTreeNode> idToNode = new HashMap<>();
        for (Categories c : all) {
            CategoryTreeNode node = new CategoryTreeNode();
            node.setCategoryId(c.getCategoryId());
            node.setParentCategoryId(c.getParentCategoryId());
            node.setCategoryName(c.getCategoryName());
            node.setSortWeight(c.getSortWeight());
            idToNode.put(node.getCategoryId(), node);
        }
        List<CategoryTreeNode> roots = new ArrayList<>();
        for (CategoryTreeNode node : idToNode.values()) {
            Long parentId = node.getParentCategoryId();
            if (parentId == null || parentId == 0L || !idToNode.containsKey(parentId)) {
                roots.add(node);
            } else {
                idToNode.get(parentId).getChildren().add(node);
            }
        }
        sortTreeRecursively(roots);
        return roots;
    }

    /**
     * 递归按 sortWeight、保持 children 有序。
     */
    private void sortTreeRecursively(List<CategoryTreeNode> nodes) {
        nodes.sort(Comparator.comparing(n -> Optional.ofNullable(n.getSortWeight()).orElse(0)));
        for (CategoryTreeNode n : nodes) {
            if (n.getChildren() != null && !n.getChildren().isEmpty()) {
                sortTreeRecursively(n.getChildren());
            }
        }
    }

    @Override
    /**
     * 查询直接子分类（仅一层）。
     */
    public List<Categories> getChildrenByParentId(Long parentCategoryId) {
        LambdaQueryWrapper<Categories> qw = new LambdaQueryWrapper<>();
        qw.eq(Categories::getParentCategoryId, parentCategoryId)
                .orderByAsc(Categories::getSortWeight, Categories::getCategoryId);
        return categoryMapper.selectList(qw);
    }

    @Override
    /**
     * 查询当前分类下的题目（不含子分类）。
     */
    public List<Question> getQuestionsByCategoryId(Long categoryId) {
        LambdaQueryWrapper<Question> qw = new LambdaQueryWrapper<>();
        qw.eq(Question::getCategoryId, categoryId)
                .orderByAsc(Question::getQuestionId);
        return questionMapper.selectList(qw);
    }

    @Override
    /**
     * 递归收集所有后代分类（返回扁平列表）。
     * 使用邻接表 parent→children + 栈（DFS）避免递归栈溢出。
     */
    public List<Categories> getAllDescendantsByParentId(Long parentCategoryId) {
        List<Categories> all = categoryMapper.selectList(null);
        Map<Long, List<Categories>> parentToChildren = new HashMap<>();
        for (Categories c : all) {
            Long pid = Optional.ofNullable(c.getParentCategoryId()).orElse(0L);
            parentToChildren.computeIfAbsent(pid, k -> new ArrayList<>()).add(c);
        }

        List<Categories> result = new ArrayList<>();
        Deque<Long> stack = new ArrayDeque<>();
        stack.push(parentCategoryId);
        while (!stack.isEmpty()) {
            Long pid = stack.pop();
            List<Categories> children = parentToChildren.get(pid);
            if (children == null || children.isEmpty()) {
                continue;
            }
            for (Categories child : children) {
                result.add(child);
                stack.push(child.getCategoryId());
            }
        }
        result.sort(Comparator.comparing((Categories c) -> Optional.ofNullable(c.getSortWeight()).orElse(0))
                .thenComparing(Categories::getCategoryId));
        return result;
    }

    @Override
    /**
     * 聚合父分类下所有后代分类的题目列表。
     */
    public List<Question> getAllQuestionsByParentCategoryId(Long parentCategoryId) {
        List<Categories> descendants = getAllDescendantsByParentId(parentCategoryId);
        if (descendants == null || descendants.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> categoryIds = new ArrayList<>(descendants.size());
        for (Categories c : descendants) {
            categoryIds.add(c.getCategoryId());
        }
        LambdaQueryWrapper<Question> qw = new LambdaQueryWrapper<>();
        qw.in(Question::getCategoryId, categoryIds)
                .orderByAsc(Question::getQuestionId);
        return questionMapper.selectList(qw);
    }
}


